package com.yunfinal.test;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import com.jfinal.kit.Kv;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.StrKit;

/**
 * 
 * ×××××××××××××××××××××××××××××××××××××××××
 * 如果项目导入报错注意： 需要使用tomcat7+ JDK７＋　的版本
 * ×××××××××××××××××××××××××××××××××××××××××
 * 
 * @ServerEndpoint 注解是一个类层次的注解，它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * @author dufuzhong
 * 
 */
@ServerEndpoint("/websocket/{ids}")
public class WebSocketController {

    //用来存放每个客户端对应的MyWebSocket对象。
    private static final Map<String, WebSocketController> WEB_SOCKET_MAP = new ConcurrentHashMap<String, WebSocketController>();
    private static final Map<String, Kv> WEB_KV = new ConcurrentHashMap<String, Kv>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    //UUID 生成的IDS
    private String ids;
    //name 昵称
    private String name;
    

    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("ids")String ids,Session session){
    	this.ids = ids;
        this.session = session;
        WEB_SOCKET_MAP.put(ids, this);
        this.name = getKvByIds(ids).getStr("name");
        
        LogKit.info("有新连接加入！当前在线人数为" + WEB_SOCKET_MAP.size());
        LogKit.info("session=" + session.getId());
        LogKit.info("ids=" + this.ids);
        
        sendAllMessage("【系统信息】欢迎：" + this.name);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
    	WEB_SOCKET_MAP.remove(this.session);
        LogKit.info("有一连接关闭！当前在线人数为" + WEB_SOCKET_MAP.size());
        LogKit.info("session=" + session.getId());
        
        sendAllMessage("【系统信息】" + this.name + " 离开了", false);
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        LogKit.info("来自客户端的消息:" + message);
        LogKit.info("session=" + session.getId());
        
        sendAllMessage(this.name + "：" + message);
    }

    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        LogKit.error("发生错误", error);
    }
    
    /**
     * 发送群消息
     */
    protected void sendAllMessage(String message){
    	sendAllMessage(message, true);
    }
    
    /**
     * 发送群消息
     * @param message 消息
     * @param isThis 是否给自己 也发
     */
    protected void sendAllMessage(String message, boolean isThis){
        for(Entry<String, WebSocketController> entry: WEB_SOCKET_MAP.entrySet()){
        	//群发消息
        	WebSocketController me = entry.getValue();
			if (isThis || me != this) {
				me.sendMessage(message);
			}
        }
    }
    
    /**
     * 指定 发送消息
     */
    protected void sendMessage(String ids, String message){
    	WebSocketController me = WEB_SOCKET_MAP.get(ids);
    	if (me != null) {
    		me.sendMessage(message);
		}else{
			this.sendMessage("【系统消息】" + getNameByIds(ids) + " 不在线");
			//留言系统 待开发
		}
    }
    
    /**
     * 向客户端 发送消息
     */
    protected void sendMessage(String message){
        try {
			this.session.getBasicRemote().sendText(message);
		} catch (IOException e) {
			LogKit.error("客户端异常", e);
		}
        //this.session.getAsyncRemote().sendText(message);
    }
    
    public static Kv getKvByIds(String ids){
    	Kv kv = WEB_KV.get(ids);
    	if (kv == null) {
			WEB_KV.put(ids, new Kv());
			return getKvByIds(ids);
		}
		return kv;
    }
    
    public static String getNameByIds(String ids){
    	return getKvByIds(ids).getStr("name");
    }
    
    public static String setNameByIds(String ids, String name){
    	if (StrKit.isBlank(name)) {
    		name = "匿名用户";
    	}
    	Kv kv = getKvByIds(ids);
    	if ( ! name.equals(kv.get("name"))) {
    		kv.set("name", name);
    		// 同步成员变量
    		WebSocketController me = WEB_SOCKET_MAP.get(ids);
    		if (me != null) {
				me.name = name;
			}
		}
    	return name;
    }
}
